from langchain_core.runnables import RunnableConfig
from langchain_core.messages import HumanMessage
from openai.types.chat import ChatCompletionMessageParam
from typing import Literal
from uuid import uuid4

from app.graph.llm import deepseek
from app.repo.chat_message import get_latest_messages
from app.conf import conf


class BaseNode:
    @classmethod
    def get_tid(cls, config: RunnableConfig) -> str:
        return config["configurable"]["thread_id"]

    @classmethod
    def get_latest_human_messages(
        cls, tid: str, n: int | None = None
    ) -> list[HumanMessage]:
        messages = get_latest_messages(tid, n, "human")
        hms = [HumanMessage(content=it.content, id=f"{it.id}") for it in messages]
        hms.reverse()
        return hms

    @classmethod
    def deepseek_r1(cls, messages: list[ChatCompletionMessageParam]):
        completion = deepseek.chat.completions.create(
            model=conf.llm_deepseek_model_r1, messages=messages, stream=True
        )

        is_answering = False  # 判断是否结束思考过程并开始回复
        rid = uuid4().hex
        cid = uuid4().hex

        for chunk in completion:
            if chunk.choices:
                delta = chunk.choices[0].delta

                if (
                    hasattr(delta, "reasoning_content")
                    and delta.reasoning_content is not None
                ):
                    # 输出思考过程
                    yield cls.new_streaming_token(
                        id=rid, type="R", token=delta.reasoning_content
                    )
                else:
                    # 开始回复
                    if delta.content != "" and not is_answering:
                        is_answering = True
                    # 输出回复过程
                    yield cls.new_streaming_token(id=cid, type="C", token=delta.content)

    @classmethod
    def new_streaming_token(cls, id: str, type: Literal["R", "C"], token: str):
        return {"id": id, "type": type, "token": token}
